home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
BasicLargeTreeModelNode.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
12KB
|
323 lines
/*
* @(#)BasicLargeTreeModelNode.java 1.11 98/02/02
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.plaf.basic;
import com.sun.java.swing.CellRendererPane;
import com.sun.java.swing.JTree;
import com.sun.java.swing.tree.*;
import com.sun.java.swing.*;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.util.*;
import java.awt.*;
/**
* BasicLargeTreeModelNode extends LargeTreeModelNode to handle painting,
* as well as stopping editing at crucial points.<p>
*
* @version 1.11 02/02/98
* @author Scott Violet
*/
class BasicLargeTreeModelNode extends LargeTreeModelNode {
public BasicLargeTreeModelNode(AbstractTreeUI treeUI, Object userObject,
int childIndex) {
super(treeUI, userObject, childIndex);
}
/**
* Repaints the receiver by messaging the TreeUI with repaintNode.
*/
public void repaint() {
((BasicTreeUI)treeUI).repaintNode(this);
}
/**
* Messages the BasicTreeUI the receiver was crated for to stop
* editing.
*/
public void cancelEditing() {
((BasicTreeUI)treeUI).completeEditing(false, true, false);
}
/**
* If the node is visible, it is repainted.
*/
public void modelChildCountChanged() {
if(getRow() != -1)
repaint();
}
/**
* Stops editing, repaints the node if only 1 child and messages
* super.
*/
public void insert(MutableTreeNode newChild, int childIndex) {
cancelEditing();
super.insert(newChild, childIndex);
if(getChildCount() == 1 && getRow() != -1)
repaint();
}
/**
* Stops editing, repaints if no children, and messages super.
*/
public void remove(int childIndex) {
cancelEditing();
super.remove(childIndex);
if(treeUI.getModel().getChildCount(getUserObject()) == 0 &&
getRow() != -1)
repaint();
}
/**
* Stops editing messages super and repaints this node if
* there are no children.
*/
public void collapse(boolean adjustTree) {
cancelEditing();
super.collapse(adjustTree);
if(adjustTree && (children == null || children.size() == 0))
repaint();
}
/**
* Stops editing messages super and repaints this node if
* there are no children.
*/
public void expand(boolean adjustTree) {
cancelEditing();
super.expand(adjustTree);
if(adjustTree && (children == null || children.size() == 0))
repaint();
}
/**
* Paints the node identified by value at the specified row.<p>
* NOTE: The receiver may not actual represent value. A
* LargeTreeModelNode is not created for each value, and as such someone
* needs to draw the values that aren't represented. Generally the
* value will either be receiver or one of its children.<p>
* NOTE: <code>child</code> may be null, which implies that child
* has not been loaded yet (or is a leaf).<p>
* NOTE: It may be faster to have the parents draw the vertical hashes
* here while descending! The only disadvantage is that it would
* require counting all the children of a given parent to determine
* the ending row. It could probably be sped up though, so this
* should be investigated.
*/
protected void paintNode(Hashtable graphicsCache, BasicTreeUI.BasicTreeUIPaintInfo pInfo, int row,
int depth,
Object value, boolean isLeaf,
boolean isExpanded, LargeTreeModelNode parent,
int childIndex, LargeTreeModelNode childNode) {
int x = (pInfo.levelOffset + depth) * pInfo.totalIndent;
int y = pInfo.rowHeight * row;
int rChildIndent = pInfo.rChildIndent;
int minX = x - (rChildIndent - 1);
int midY = y + pInfo.halfRowHeight;
int maxY = y + (pInfo.rowHeight - 1);
Color hColor = pInfo.hashColor;
Graphics g = pInfo.g;
BasicTreeUI ui = (BasicTreeUI)treeUI;
TreeModel treeModel = pInfo.treeModel;
Component rComponent;
rComponent = pInfo.renderer.getTreeCellRendererComponent
(pInfo.tree, value,ui.isRowSelected(row), isExpanded, isLeaf, row,
(row == pInfo.leadIndex));
if(hColor != null) {
int lastChildIndex = childIndex;
LargeTreeModelNode lastParent = parent;
g.setColor(hColor);
/* Draw the horizontal line. */
if(row != 0 || pInfo.levelOffset == 1)
ui.drawHorizontalPartOfLeg( g, pInfo.tree, midY, minX, x );
}
/* Only draw icons if has children. */
if (!isLeaf && (childNode == null ||
treeModel.getChildCount(value) > 0)) {
if (isExpanded) {
if(pInfo.expandedIcon != null)
cacheIconPainting( graphicsCache, pInfo.expandedIcon, minX, midY );
//ui.drawCentered(pInfo.tree, g, pInfo.expandedIcon, minX, midY);
} else {
if(pInfo.collapsedIcon != null)
cacheIconPainting( graphicsCache, pInfo.collapsedIcon, minX, midY );
//ui.drawCentered(pInfo.tree, g, pInfo.collapsedIcon, minX, midY);
}
}
ui.rendererPane.paintComponent(g, rComponent, pInfo.tree, x, y,
rComponent.getPreferredSize().width,
pInfo.rowHeight, true);
}
protected void cacheIconPainting( Hashtable graphicsCache, Icon icon, int minX, int midY ) {
graphicsCache.put( new Point( minX, midY ), icon );
}
public static void paintCachedGraphics( Hashtable graphicsCache, Graphics g, JTree tree, BasicTreeUI ui ) {
Enumeration keys = graphicsCache.keys();
while ( keys.hasMoreElements() ) {
Point point = (Point)keys.nextElement();
Icon icon = (Icon)graphicsCache.get( point );
ui.drawCentered( tree, g, icon, point.x, point.y );
}
}
/**
* Paints all the children that do not have LargeTreeModelNodes by
* messaging paintNode.<p>
* <code>beginRow</code> specifies the beginining row to paint
* at and <code>endRow</code> specifies the row to stop painting
* at. <code>lowerTest</code> specifies the potential lower row
* to start painting at and <code>upperTest</code> specifies the
* potential upper row to start painting at.
*/
protected void paintChildren(Hashtable graphicsCache, BasicTreeUI.BasicTreeUIPaintInfo pInfo,
int lowerTest,
int upperTest, int beginRow, int endRow,
int depth, int lowerChildIndex) {
int minRow = Math.max(beginRow, lowerTest);
int minIndex = (minRow - lowerTest) + lowerChildIndex;
int firstIndex = minIndex;
int maxIndex = (Math.min(endRow, upperTest) - lowerTest) +
lowerChildIndex;
Object childValue;
while(minIndex <= maxIndex) {
childValue = pInfo.treeModel.getChild(getUserObject(), minIndex);
paintNode(graphicsCache, pInfo, minRow, depth, childValue,
pInfo.treeModel.isLeaf(childValue), false, this,
minIndex, null);
minIndex++;
minRow++;
}
}
/**
* Paints this node if currentRow[0] is between beginRow and
* endRow by messaging paintNode. Will then message all the children
* will paint, and for nodes that are in between beginRow/endRow
* and don't have an LargeTreeModelNode paintChildren will be messaged.
*/
protected boolean paint(Hashtable graphicsCache, BasicTreeUI.BasicTreeUIPaintInfo pInfo,
int currentRow[], int beginRow, int endRow,
int depth) {
// Current row of the receiver.
int startRow = currentRow[0];
if(currentRow[0] >= beginRow && currentRow[0] <= endRow)
paintNode(graphicsCache, pInfo, currentRow[0], depth, getUserObject(),
false, isExpanded(), (LargeTreeModelNode)getParent(),
getChildIndex(), this);
currentRow[0]++;
if(currentRow[0] > endRow)
return true;
depth++;
if(isExpanded) {
BasicLargeTreeModelNode aChild;
int childIndex;
int lastChildIndex = 0;
int lastRow = currentRow[0];
int newRow;
// Number of children, from the model, minus 1.
int modelChildCount = pInfo.treeModel.
getChildCount(getUserObject()) - 1;
// Will be set to row of our last child, if it is expanded.
int lastChildRow = -1;
for(int counter = 0, maxCounter = getChildCount();
counter < maxCounter; counter++) {
aChild = (BasicLargeTreeModelNode)getChildAt(counter);
childIndex = aChild.childIndex;
if(childIndex != lastChildIndex) {
/* Subtract one to not paint this child, that will be
done below. */
newRow = (childIndex - lastChildIndex) + lastRow - 1;
if(lastRow <= endRow && (newRow >= beginRow ||
newRow <= endRow)) {
paintChildren(graphicsCache, pInfo, lastRow, newRow,
beginRow, endRow, depth,
lastChildIndex);
}
}
currentRow[0] += (childIndex - lastChildIndex);
if(currentRow[0] > endRow) {
// The children of this node go beyond the visible
// region, paint the legs from the starting row to the
// end row, don't actually need the real last y as it'll
// be clipped anyway.
((BasicTreeUI)treeUI).drawVerticalPartOfLeg(pInfo.g, pInfo.tree, depth-1,
startRow * pInfo.rowHeight,
endRow * pInfo.rowHeight, pInfo.rowHeight,
pInfo.rowHeight);
return true;
}
// If this child is the last child in the model, record
// its row.
if(childIndex == modelChildCount)
lastChildRow = currentRow[0];
aChild.paint(graphicsCache, pInfo, currentRow, beginRow, endRow, depth);
lastRow = currentRow[0];
lastChildIndex = childIndex + 1;
}
childIndex = pInfo.treeModel.getChildCount(getUserObject()) - 1;
if(childIndex >= lastChildIndex) {
newRow = (childIndex - lastChildIndex) + lastRow;
if(lastRow <= endRow && (newRow >= beginRow ||
newRow <= endRow)) {
paintChildren(graphicsCache, pInfo, lastRow, newRow,
beginRow, endRow, depth,
lastChildIndex);
}
currentRow[0] += (childIndex - lastChildIndex) + 1;
}
// If we have children, we need to draw the legs from the start
// row down to either lastChildRow, or currentRow[0]
// lastChildRow will be valid if our last child is expanded.
if(modelChildCount >= 0) {
((BasicTreeUI)treeUI).drawVerticalPartOfLeg(pInfo.g, pInfo.tree, depth-1,
startRow * pInfo.rowHeight,
((lastChildRow == -1) ? (currentRow[0] - 1) :
lastChildRow) * pInfo.rowHeight, pInfo.rowHeight,
pInfo.rowHeight);
}
}
return false;
}
/**
* This will paint all nodes in the tree "below" this one. This method is usually
* called on the "root" node.
*/
public void paintAll(BasicTreeUI.BasicTreeUIPaintInfo pInfo,
int currentRow[], int beginRow, int endRow,
int depth, BasicTreeUI ui ) {
Hashtable graphicsCache = new Hashtable();
paint( graphicsCache, pInfo, currentRow, beginRow, endRow, depth );
paintCachedGraphics( graphicsCache, pInfo.g, pInfo.tree, ui );
}
}